using System;
using UnityEngine;

public abstract class UnitController : LocatableObjectController
{
    protected CharPrototype m_pProto;
    protected sbyte m_moveMode;
    protected bool m_isDead;
    protected bool m_isInCombat;

    protected bool m_isMoving;
    protected Vector3 m_facePos;
    protected Vector3 m_tgtPos;
    protected float m_keepDist;
    protected uint m_iMovePathCount;
    protected Vector3[] m_fMovePath;

    protected bool m_isTurning;
    protected Vector3 m_tgtDir;

    public abstract string GetDisplayName();
    public abstract string GetName();

    void OnGUI()
    {
        var worldPos = new Vector3(transform.position.x,
            transform.position.y + 1.0f, transform.position.z);
        var screenPos = Camera.main.WorldToScreenPoint(worldPos);
        var uiPos = new Vector2(screenPos.x, Screen.height - screenPos.y);

        var name = GetDisplayName();
        var nameSize = GUI.skin.label.CalcSize(new GUIContent(name));
        GUI.color = Color.yellow;
        GUI.Label(new Rect(uiPos.x - nameSize.x / 2,
            uiPos.y - nameSize.y - 1.0f, nameSize.x, nameSize.y), name);

        var hpStr = ((double)GetS64Value((int)UNIT64_PROPERTIES.UNIT64_FIELD_HP) /
            GetS64Value((int)UNIT64_PROPERTIES.UNIT64_FIELD_HP_MAX)).ToString("P0");
        var hpSize = GUI.skin.label.CalcSize(new GUIContent(hpStr));
        GUI.color = Color.red;
        GUI.Label(new Rect(uiPos.x - hpSize.x / 2,
            uiPos.y - hpSize.y - 22.0f, hpSize.x, hpSize.y), hpStr);
    }

    public override void LoadFromCreatePacket(NetPacket pck)
    {
        base.LoadFromCreatePacket(pck);

        pck.Read(out uint charTypeId);
        pck.Read(out m_moveMode);
        pck.Read(out m_isDead);
        pck.Read(out m_isInCombat);
        pck.Read(out m_isMoving);
        if (m_isMoving)
        {
            LoadFromCreateUpdateMoveBlock(pck);
        }
        pck.Read(out m_isTurning);
        if (m_isTurning)
        {
            LoadFromCreateUpdateTurnBlock(pck);
        }

        m_pProto = DBMgr.Instance.tblCharPrototype.GetEntry(charTypeId);
        Debug.Assert(m_pProto != null);
    }

    public void LoadFromCreateUpdateMoveBlock(NetPacket pck)
    {
        var pckEx = new NetPacketHelper(pck);
        pckEx.Read(out m_facePos);
        pckEx.Read(out m_tgtPos);
        pck.Read(out m_keepDist);
        pck.Read(out m_iMovePathCount);
        pck.Read(out UInt16 iPathCount);
        m_fMovePath = new Vector3[m_iMovePathCount + iPathCount];
        for (int i = (int)m_iMovePathCount, n = m_fMovePath.Length; i < n; ++i)
        {
            pckEx.Read(out m_fMovePath[i]);
        }
    }

    public void LoadFromCreateUpdateTurnBlock(NetPacket pck)
    {
        var pckEx = new NetPacketHelper(pck);
        pckEx.Read(out m_tgtDir);
    }

    public float GetMoveSpeed()
    {
        return GetF32Value((int)UNIT_PROPERTIES.UNIT_FLOAT_MOVE_SPEED) *
            Math.Max(0, 1 + GetF32Value((int)UNIT_PROPERTIES.UNIT_FLOAT_MOVE_SPEED_INC));
    }

    public bool IsDead()
    {
        return m_isDead;
    }
    public void Dead()
    {
        m_isDead = true;
    }
    public void Revive()
    {
        m_isDead = false;
    }
}
